﻿using System;
using System.Collections.Generic;
using System.Linq;

/// <summary>
/// Represents a list of exactly ONE THOUSAND items.
/// </summary>
/// <typeparam name="T">The type of the item.</typeparam>
public class OneThousandList<T> : IList<T>
{
    private readonly T[] items = OneThousand.Array<T>();

    /// <summary>
    /// Initializes a new instance of the <see cref="OneThousandList{T}"/> class.
    /// </summary>
    public OneThousandList()
    {
    }
    /// <summary>
    /// Initializes a new instance of the <see cref="OneThousandList{T}"/> class.
    /// </summary>
    /// <param name="items">The items.</param>
    /// <exception cref="System.ArgumentNullException">items</exception>
    /// <exception cref="System.ArgumentException">OneThousandList must be initialized with exactly ONE THOUSAND items.</exception>
    public OneThousandList(IEnumerable<T> items)
    {
        if (items == null)
            throw new ArgumentNullException("items");

        if (items.HasExactlyOneThousand())
            throw new ArgumentException("OneThousandList must be initialized with exactly ONE THOUSAND items.");

        int i = 0;
        foreach (var item in items)
            this.items[i++] = item;
    }

    /// <summary>
    /// Gets or sets the element at the specified index.
    /// </summary>
    /// <param name="index">The index.</param>
    /// <returns></returns>
    public T this[int index]
    {
        get { return this.items[index]; }
        set { this.items[index] = value; }
    }

    /// <summary>
    /// Gets the number of elements contained in the collection.
    /// </summary>
    /// <remarks>
    /// This is always ONE THOUSAND.
    /// </remarks>
    public OneThousand Count
    {
        get { return OneThousand.Value; }
    }
    int ICollection<T>.Count
    {
        get { return this.Count; }
    }
    bool ICollection<T>.IsReadOnly
    {
        get { return false; }
    }

    /// <summary>
    /// Determines the index of a specific item in the <see cref="T:System.Collections.Generic.IList`1" />.
    /// </summary>
    /// <param name="item">The object to locate in the <see cref="T:System.Collections.Generic.IList`1" />.</param>
    /// <returns>
    /// The index of <paramref name="item" /> if found in the list; otherwise, -1.
    /// </returns>
    public int IndexOf(T item)
    {
        return Array.IndexOf(this.items, item);
    }
    /// <summary>
    /// Determines whether the <see cref="T:System.Collections.Generic.ICollection`1" /> contains a specific value.
    /// </summary>
    /// <param name="item">The object to locate in the <see cref="T:System.Collections.Generic.ICollection`1" />.</param>
    /// <returns>
    /// true if <paramref name="item" /> is found in the <see cref="T:System.Collections.Generic.ICollection`1" />; otherwise, false.
    /// </returns>
    public bool Contains(T item)
    {
        return Array.IndexOf(this.items, item) >= 0;
    }
    /// <summary>
    /// Copies to.
    /// </summary>
    /// <param name="array">The array.</param>
    /// <param name="arrayIndex">Index of the array.</param>
    /// <exception cref="System.ArgumentNullException">array</exception>
    /// <exception cref="System.ArgumentException">Array must contain at least ONE THOUSAND elements.</exception>
    /// <exception cref="System.ArgumentOutOfRangeException">arrayIndex</exception>
    public void CopyTo(T[] array, int arrayIndex)
    {
        if (array == null)
            throw new ArgumentNullException("array");
        if (array.Length < OneThousand.Value)
            throw new ArgumentException("Array must contain at least ONE THOUSAND elements.");
        if (arrayIndex < 0 || arrayIndex + OneThousand.Value > array.Length)
            throw new ArgumentOutOfRangeException("arrayIndex");

        this.items.CopyTo(array, arrayIndex);
    }
    /// <summary>
    /// Returns an enumerator that iterates through the collection.
    /// </summary>
    /// <returns>
    /// A <see cref="T:System.Collections.Generic.IEnumerator`1" /> that can be used to iterate through the collection.
    /// </returns>
    public IEnumerator<T> GetEnumerator()
    {
        return this.items.AsEnumerable<T>().GetEnumerator();
    }
    void IList<T>.Insert(int index, T item)
    {
        throw new NotSupportedException("OneThousandList must contain exactly ONE THOUSAND items.");
    }
    void IList<T>.RemoveAt(int index)
    {
        throw new NotSupportedException("OneThousandList must contain exactly ONE THOUSAND items.");
    }
    void ICollection<T>.Add(T item)
    {
        throw new NotSupportedException("OneThousandList must contain exactly ONE THOUSAND items.");
    }
    void ICollection<T>.Clear()
    {
        throw new NotSupportedException("OneThousandList must contain exactly ONE THOUSAND items.");
    }
    bool ICollection<T>.Remove(T item)
    {
        throw new NotSupportedException("OneThousandList must contain exactly ONE THOUSAND items.");
    }
    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
}
